package me.yricky.alia.data.shape

import me.yricky.alia.data.base.Coord
import java.lang.Integer.max
import java.lang.Integer.min

/**
 * @author Yricky
 * @date 2022/1/27
 */
data class Box(
    val lt: Coord,
    val rb: Coord
) : Shape {
    override val vertices: List<Coord> by lazy{
        listOf(lt, Coord(rb.x,lt.y),rb, Coord(lt.x,rb.y),lt)
    }

    override val bBox: Box = this

    override fun toString(): String {
        return "Box[lt(${lt.x},${lt.y}),rb(${rb.x},${rb.y})]"
    }
}

fun Box.contains(shape: Shape):Boolean{
    val sBBox = shape.bBox
    return lt.x <= sBBox.lt.x &&
            lt.y <= sBBox.lt.y &&
            rb.x >= sBBox.rb.x &&
            rb.y >= sBBox.rb.y
}

fun Box.isOverlap(box:Box):Boolean{
    return (lt.x < box.rb.x && rb.x > box.lt.x) && (lt.y < box.rb.y && rb.y > box.lt.y)
}

val defLt:Coord = Coord(0,0)
val defRb:Coord = Coord(1,1)
val defBox = Box(defLt, defRb)

inline val Box.width:Int get() = (rb.x-lt.x).coerceAtLeast(1)
inline val Box.height:Int get() = (rb.y-lt.y).coerceAtLeast(1)
inline val Box.center: Coord get() = Coord((lt.x+rb.x)/2,(lt.y+rb.y)/2)


fun mergeBBox(boxes:List<Box>): Box {
    if(boxes.isEmpty()){
        return defBox
    }

// Performance Score: 784x
    var ltx = boxes[0].lt.x
    var lty = boxes[0].lt.y
    var rbx = boxes[0].rb.x
    var rby = boxes[0].rb.y
    boxes.forEach {
        ltx = min(ltx,it.lt.x)
        lty = min(lty,it.lt.y)
        rbx = max(rbx,it.rb.x)
        rby = max(rby,it.rb.y)
    }
    return Box(Coord(ltx,lty),Coord(rbx,rby))

// Performance Score: 470x
//    return boxes.reduce{ b1,b2 ->
//        Box(
//            Coord(min(b1.lt.x,b2.lt.x),min(b1.lt.y,b2.lt.y)),
//            Coord(max(b1.rb.x,b2.rb.x),max(b1.rb.y,b2.rb.y))
//        )
//    }

// Performance Score: 197x
//    return Polygon(boxes.flatMap { listOf(it.lt,it.rb) }).bBox
}

